﻿using System;
using System.Linq;
using System.Windows.Forms;
using Iveonik.ConsoleWrapper;

namespace ConsoleDemo
{
    internal class Program
    {
        private const string UsageExample =
            @"Demo application for ConsoleWrapper library. Usage:

ConsoleDemo.exe [options]

  options list:
    /h /help /?                 - This help screen.
    /pause                      - Run in key input waiting mode.
    somevalue                   - Non-named params
    /name={value}               - named parameter with value

  Parameter's names is case insensitive. You can start parameters with: '/',
  '-', '--'. 
  Parameter's value can be divided from name with: '=' and ':'.
  So, the following variants are equal:

  ConsoleDemo.exe /name=1
  ConsoleDemo.exe -Name=1
  ConsoleDemo.exe --nAmE:1
  
  To make additional information (start, finish time, duration) visible, you 
  can use additional Trace listeners, like 
  System.Diagnostics.ConsoleTraceListener. Uncomment <system.diagnostics> 
  section to see the Trace's messages. Another useful listener is
  System.Diagnostics.TextWriterTraceListener class.
";

        private static void Main(string[] args)
        {
            // Setup wrapper
            AppWrapper wrapper = new AppWrapper()
                .SetUsageExample(UsageExample)
                .SetSilentModeParameter("silent")
                .SetMutexNameGenerators(GetBaseMutexName, GetDbNameMutexName)
                .SetAdmissibleParameters("pause", "name", "silent", "") // "" - to allow unnamed params
                //.AddMutuallyExclusiveRule("pause", "name") // uncomment to prohibit of using these parameters together
                .AddBeforeStart(OnBeforeStart)
                .AddAfterFinish(OnAfterFinish)
                .AddUnhandledException(OnUnhandledException)
                ;

            // Start the main processing method.
            wrapper.Run(MainProc);
        }

        private static void MainProc(AppWrapper appWrapper)
        {
            Parameters parameters = appWrapper.Parameters;

            // Output arguments
            Console.WriteLine("");

            if (parameters.GetAllNames().Any())
            {
                Console.WriteLine("Found parameters:");
                foreach (var name in parameters.GetAllNames())
                {
                    Console.Write(name + " : ");
                    foreach (var value in parameters.GetValues(name))
                    {
                        Console.Write("\"" + value + "\", ");
                    }
                    Console.WriteLine();
                }
            }
            else
            {
                Console.WriteLine("None at all parameter found.");
            }

            Console.WriteLine("");

            // Check for some argument
            if (parameters.HasParameter("pause"))
            {
                Console.WriteLine("Press enter to finish the application...");
                Console.ReadLine();
            }

        }

        private static void OnUnhandledException(object sender,
            AppWrapper.UnhandledExceptionEventArgs unhandledExceptionEventArgs)
        {
            Console.WriteLine("Ups... Something wrong:");
            Console.WriteLine(unhandledExceptionEventArgs.UnhandledException.ToString());
        }

        private static void OnBeforeStart(object sender, EventArgs eventArgs)
        {
            Console.WriteLine("Application started. Start time is placed in your trace listeners.");
        }

        private static void OnAfterFinish(object sender, AppWrapper.AfterFinishEventArgs afterFinishEventArgs)
        {
            Console.WriteLine(
                "Application finished. Finish time, duration of running, sum up info are placed in your trace listeners.");
        }

        /// <summary>
        /// Mutex for preventing running 2 copies from one place.
        /// </summary>
        /// <returns>Adopted for Mutex path of app.</returns>
        private static string GetBaseMutexName()
        {
            return Application.ExecutablePath.Replace(':', '_').Replace('\\', '_');
        }

        /// <summary>
        /// Imagine, this is mutex for preventing processing in some DB in the parallel mode.
        /// </summary>
        /// <returns>Mutex name, depends on db name.</returns>
        private static string GetDbNameMutexName()
        {
            return "ConsoleDemo-SomeDbConnectionString";
        }
    }
}
